using System;
using System.Reflection;
using System.Web;
using System.Web.SessionState;
using System.Text.RegularExpressions;
using System.Text;

namespace sb.core.WS {
	public class WebServiceRestScriptFormatter {
		public string GetProxyString(string virtualPath) {
			bool generateDebugProxy=false;

			Type webServiceDataType=Type.GetType("System.Web.Script.Services.WebServiceData,System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
			object webServiceData=null;

			try {
                webServiceData = webServiceDataType.InvokeMember("GetWebServiceData", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Static,
                    null, null, new object[] { HttpContext.Current, virtualPath }
                );
			}
			catch (Exception ex) {
				return String.Empty;
			}

            Type webServiceClientProxyGeneratorType = Type.GetType("System.Web.Script.Services.WebServiceClientProxyGenerator,System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");

            object webServiceClientProxyGenerator = webServiceClientProxyGeneratorType.InvokeMember("",
                BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic,null, 
                null, new object[] { virtualPath, generateDebugProxy }
            );

            string proxyScript = (string)webServiceClientProxyGeneratorType.InvokeMember("GetClientProxyScript",
                BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance,
                null, webServiceClientProxyGenerator, new object[] { webServiceData }
            );

            return FormatMootoolsWebService(proxyScript,virtualPath);
		}

		private string FormatMootoolsWebService(string source,string virtualPath) {
			Regex classNameRx=new Regex(@"^(?<className>.*?)=function",RegexOptions.Multiline);
			Match classNameMatch=classNameRx.Match(source);
			if (classNameMatch!=null) {
				string className=classNameMatch.Groups["className"].Value;

				string newClassDecleration=
@"
addNamespace(""{0}"");
{0}Class=new Class({{
	Extends:WebService,
	url:""{2}"",
	{1}
}});
{0}=new {0}Class();
";
				StringBuilder methodsDecleration=new StringBuilder();
				Regex methodRx=new Regex(@"(?<methodName>\w+):function\((?<params>(?:.*,)+)*succeededCallback, failedCallback, userContext\)");
				MatchCollection methods=methodRx.Matches(source);
				foreach (Match methodMatch in methods) {
					string jsonedParams=methodMatch.Groups["params"].Value;
					jsonedParams=Regex.Replace(jsonedParams,@"(.*?),","$1:$1,");
					if (jsonedParams.EndsWith(",")) jsonedParams=jsonedParams.Remove(jsonedParams.Length-1,1);
					jsonedParams="{"+jsonedParams+"}";

					methodsDecleration.AppendFormat(
@"
{0}:function ({1}onSuccess,onFailure) {{
	return WebService.prototype.send.apply({3},[""{0}"",{2},onSuccess,onFailure]);
}},",
						methodMatch.Groups["methodName"].Value,
						methodMatch.Groups["params"].Value,
						jsonedParams,
						className
					);
				}
				if (methodsDecleration.Length>0) methodsDecleration.Remove(methodsDecleration.Length-1,1);

				return String.Format(
					newClassDecleration,
					className,
					methodsDecleration.ToString(),
					virtualPath
				);
			}
			return "/* couldn't read source \n\n"+source+"*/";
		}
	}
}
